package utils

import (
	"fmt"
	"github.com/gogf/gf/frame/g"
	"github.com/gomodule/redigo/redis"
	"github.com/tebeka/selenium"
	"io/fs"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"regexp"
	"time"

	"github.com/cavaliergopher/grab/v3"
	"github.com/gogf/gf/util/gconv"
	"github.com/tealeg/xlsx"
)

func IsHttpHref(href string) bool {
	reg := regexp.MustCompile(`^http://|https://`)
	if reg.Match(gconv.Bytes(href)) {
		return true
	} else {
		return false
	}
}

func RandomSleep() {
	time.Sleep(time.Duration(rand.Intn(25)+10) * time.Second)
}

type Account struct {
	Email    string
	Password string
	Cookie   []selenium.Cookie
}

var Accounts []Account

var UsedAccounts []Account

type AccountCookie struct {
	Email          string            `json:"email"`
	Cookie         []selenium.Cookie `json:"cookie"`
	DownloadCounts int               `json:"download_counts"`
}

// 初始化的时候加载

func LoadAccount() {
	// 从配置文件中读取账号列表
	accountList := g.Cfg().GetArray("account_list")
	for _, account := range accountList {
		var acc Account
		accountMap := account.(map[string]interface{})
		acc.Email = accountMap["email"].(string)
		acc.Password = accountMap["password"].(string)
		Accounts = append(Accounts, acc)

		SetAccountToRedis(acc.Email, acc.Password)
	}
}

func LoadAccountFromExcel() {
	// 从配置文件中读取账号列表
	accountPath := g.Cfg().GetString("account_excel.path")

	excelFile, err := xlsx.OpenFile(accountPath)
	if err != nil {
		log.Fatal(err)
	}
	var accountList []Account

	for _, sheet := range excelFile.Sheets {
		for _, row := range sheet.Rows {
			// 获取 A 列的值
			cellA := row.Cells[0].String()
			// 获取 B 列的值
			cellB := row.Cells[1].String()

			accountList = append(accountList, Account{Email: cellA, Password: cellB})
			SetAccountToRedis(cellA, cellB)

		}
	}

	//fmt.Println("accountList:", accountList)
}

// 随机获取一个账号

func GetAccounts() {

	if len(Accounts) == 0 {
		// 清空 UsedAccounts
		//UsedAccounts = nil

		conn := g.Redis().Conn()
		defer conn.Close()
		values, err := redis.StringMap(conn.Do("HGETALL", LINKABLE_ACCOUNT_REDIS))

		if err != nil {
			fmt.Println("获取ACCOUNT列表失败", err)
			log.Fatal("今日无账号可用")
		}

		// 将值转换为 []Account 类型
		Accounts = make([]Account, 0, len(values))
		for key, value := range values {
			var account Account
			account.Email = key
			account.Password = value
			Accounts = append(Accounts, account)
		}

	}

	//fmt.Println("Accounts:", Accounts)
}

func RandAccount() *Account {
	GetAccounts()

	if len(Accounts) == 0 {
		log.Fatal("今日无账号可用")
	}

	//fmt.Println("Accounts:", Accounts)
	//fmt.Println("UsedAccounts:", UsedAccounts)

	// 使用第一个账号
	account := Accounts[0]
	fmt.Println("使用账号:", account)

	// 在此处执行你的方法逻辑

	// 将已使用的账号从 Accounts 中删除，并添加到 UsedAccounts 中
	Accounts = Accounts[1:]

	//fmt.Println("Accounts:", Accounts)
	return &account
}

// 获取当前时间自然周
func WeekTime(title string) string {
	now := time.Now()
	weekStart := now.AddDate(0, 0, -int(now.Weekday())+1)
	weekEnd := weekStart.AddDate(0, 0, 6)
	weektime := fmt.Sprintf("%d.%02d.%02d-%d.%02d.%02d", weekStart.Year(), weekStart.Month(), weekStart.Day(), weekEnd.Year(), weekEnd.Month(), weekEnd.Day())
	driverPath := g.Cfg().GetString("download.path")
	isExist, path, err := CheckFileExist(driverPath, title)
	if isExist == true && err == nil {
		return path
	} else {
		reg := regexp.MustCompile(`[\\/:*?"<>|]`)
		title = reg.ReplaceAllString(title, "_")
		folderName := filepath.Join(driverPath, weektime, title)
		// 创建文件夹
		err = os.MkdirAll(folderName, os.ModePerm)
		if err != nil {
			fmt.Println("创建文件夹失败:", err)
		}
		return folderName
	}

}

// 判断文件夹是否存在

func CheckFileExist(root string, fileName string) (bool, string, error) {
	// 遍历文件夹
	found := false
	cPath := ""
	err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		// 检查是否为指定名称的文件夹
		if d.Name() == fileName {
			found = true
			if err != nil {
				return err
			}
			//fmt.Println("path:", path)
			cPath = path
		}

		return nil
	})

	if err != nil {
		return false, cPath, err
	}

	return found, cPath, nil
}

func Unique(urls []string) []string {

	// 使用map[string]bool进行去重
	uniqueURLs := make(map[string]bool)
	for _, url := range urls {
		uniqueURLs[url] = true
	}

	// 将去重后的URL放入新的切片
	var deduplicatedURLs []string
	for url := range uniqueURLs {
		deduplicatedURLs = append(deduplicatedURLs, url)
	}
	var result []string
	// 打印去重后的URL
	for _, url := range deduplicatedURLs {
		result = append(result, url)
	}
	return result
}

func DownloadImageGrab(url, filename string) error {
	//// 检查文件是否已存在
	//if _, err := os.Stat(filename); err == nil {
	//	fmt.Println("File already exists:", filename)
	//	return nil
	//}

	// 打开日志文件
	file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0777)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// 设置日志输出到文件
	log.SetOutput(file)

	client := grab.NewClient()
	req, err := grab.NewRequest(".", url)
	if err != nil {
		fmt.Println(err)
		log.Println(err)

		return err
	}
	req.Filename = filename
	resp := client.Do(req)

	if err := resp.Err(); err != nil {
		fmt.Println(err)
		log.Println(err)

		return err
	}
	fmt.Printf("Download saved to %v\n", resp.Filename)
	RandomSleep()

	// start UI loop
	t := time.NewTicker(500 * time.Millisecond)
	defer t.Stop()

	return nil
}

func ClearPath(filePath string) string {
	// 定义要替换的特殊字符的正则表达式模式
	pattern := `[\\/:*?"<>|]`

	// 创建正则表达式对象
	reg := regexp.MustCompile(pattern)

	// 使用空字符串替换特殊字符
	cleanedFilePath := reg.ReplaceAllString(filePath, "")

	return cleanedFilePath
}
